package com.lakeworks.service.api;

import com.lakeworks.common.annotation.MethodHandler;
import com.lakeworks.common.annotation.MethodName;
import com.lakeworks.common.core.domain.AjaxResult;
import com.lakeworks.domain.vo.MethodMapping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.*;

@Component
public class DetectMethodAnnotation implements ApplicationContextAware, InitializingBean {


    private ApplicationContext applicationContext;

    private static final Logger log = LoggerFactory.getLogger(DetectMethodAnnotation.class);

    //存储类-方法
    private HashMap<String, List<MethodMapping>> classMethodMap = new HashMap<>();

    /**
     * 初始化容器后解析所有包含MethodHandler注解的类中包含Name注解的方法
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        //获取包含注解MethodHandler的类
        Map<String, Object> methodHandlerMap = applicationContext.getBeansWithAnnotation(MethodHandler.class);
        methodHandlerMap.forEach((k, v) -> {
            Class<?> clazz = v.getClass();
            Method[] methods = clazz.getDeclaredMethods();//获取所有的方法
            List<MethodMapping> methodMappings = new ArrayList<>();
            for (Method method : methods) {
                if (method.isAnnotationPresent(MethodName.class) && (method.getReturnType() == AjaxResult.class)) {
                    MethodName nameAnnotation = method.getAnnotation(MethodName.class);
                    methodMappings.add(new MethodMapping(nameAnnotation.value().name(), method));
                }
            }
            if (!methodMappings.isEmpty()) {
                classMethodMap.put(clazz.getName(), methodMappings);
            }
        });
    }

    /**
     * 执行
     *
     * @param name
     * @return
     */
    public <T> AjaxResult execute(T methodHandler,String name, Object... parameters) throws Exception {
        log.info("classMethodMap-----[{}]",classMethodMap);
        if (!classMethodMap.containsKey(methodHandler.getClass().getName())) {
            return AjaxResult.error("类[" + methodHandler.getClass().getName() + "]未使用注解@MethodHandler注册或未发现任何使用@Name注解的非继承方法");
        }
        List<MethodMapping> methodMappings = classMethodMap.get(methodHandler.getClass().getName());
        for (MethodMapping methodMapping : methodMappings) {
            if(methodMapping.name.equals(name)){
                return (AjaxResult) methodMapping.method.invoke(methodHandler, parameters);
            }
        }
        return AjaxResult.error("未发现使用注解 @Name(\"" + name + "\") 为的方法");
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}